﻿//-----------------------------------------------------------------------
// <copyright file="XAMLFile.cs" company="INL sprl">
//     Copyright 2010 INL sprl.
// </copyright>
// Fabrice avaux : Date de création 16/01/2009
//-----------------------------------------------------------------------

namespace ParseXAML
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Xml;

    internal abstract class NamesAndUidsBase
    {
        Global global;
        string attributeName;

        internal NamesAndUidsBase(Global global, XmlElement node, string attributeName)
        {
            this.global = global;
            this.attributeName = attributeName;
            this.GetAllNameAndUid(node);
        }

        /// <summary>
        /// Les noms des XAML déjà généré
        /// </summary>
        protected List<String> namesInXAML = new List<string>();

        /// <summary>
        /// Generate a new name (use the <c ref="namesInXAML"/> as reference) to generate a new name.
        /// If the name suggested is not already used and contains number, this name is used,
        /// else it adds a suffix _x where x is increment to find a unique name.
        /// The name is added to collection <c ref="namesInXAML"/>.
        /// </summary>
        /// <param name="baseName">Suggestion for the name</param>
        /// <returns>Returns a new unique name in the XAML</returns>
        internal string GenerateNewName(string baseName)
        {
            if ((Utils.GetNumerOfDigit(baseName) > 0) &&
                (this.namesInXAML.IndexOf(baseName) == -1)) // we need to escapte TextBlock, TextBox name for exemple
            {
                this.namesInXAML.Add(baseName);
                return baseName;
            }

            for (int i = 1; ; i++)
            {
                string newName = string.Concat(baseName, "_", i.ToString());
                if (this.namesInXAML.IndexOf(newName) == -1)
                {
                    this.namesInXAML.Add(newName);
                    return newName;
                }
            }
        }

        /// <summary>
        /// Scan all the document to find name and Uid.
        /// store all result in <c ref="namesInXAML"/> and <c ref="uidInXAML"/>
        /// </summary>
        /// <param name="node">The root element</param>
        private void GetAllNameAndUid(XmlElement node)
        {
            foreach (var n in node.ChildNodes)
            {
                if (n is XmlElement)
                {
                    this.GetAllNameAndUid((XmlElement)n);
                }
            }

            XmlAttribute name = this.GetName(node);
            if (name != null)
            {
                if (this.namesInXAML.IndexOf(name.Value) != -1)
                    global.AddMessage(Message.eType.Warning, "The {0} {1} is duplicated", attributeName, name.Value);
                else
                    this.namesInXAML.Add(name.Value);
            }
        }

        protected abstract XmlAttribute GetName(XmlElement node);
    }

    internal class Names : NamesAndUidsBase
    {
        internal Names(Global global, XmlElement node)
            : base( global, node, "name" )
        {
        }

        protected override XmlAttribute GetName(XmlElement node)
        {
            return Utils.GetName(node);
        }
    }

    internal class Uids : NamesAndUidsBase
    {
        internal Uids(Global global, XmlElement node)
            : base(global, node, "Uid")
        {
        }

        protected override XmlAttribute GetName(XmlElement node)
        {
            return node.GetAttributeNode("Uid", NamespaceAssociations.nsXamlName);
        }
    }

}
